package com.maktoub.project.controller;

import cn.hutool.core.date.DateTime;
import cn.hutool.http.HttpResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.maktoub.apiclientstart.client.ApiInterfaceClient;
import com.maktoub.common.model.entity.InterfaceInfo;
import com.maktoub.common.model.entity.User;
import com.maktoub.project.annotation.AuthCheck;
import com.maktoub.project.common.*;
import com.maktoub.project.exception.BusinessException;
import com.maktoub.project.model.dto.interfaceinfo.InterfaceInfoAddRequest;
import com.maktoub.project.model.dto.interfaceinfo.InterfaceInfoInvokeRequest;
import com.maktoub.project.model.dto.interfaceinfo.InterfaceInfoQueryRequest;
import com.maktoub.project.model.dto.interfaceinfo.InterfaceInfoUpdateRequest;
import com.maktoub.project.model.entity.InterfaceCollectInfo;
import com.maktoub.project.model.enums.InterfaceStatusEnum;
import com.maktoub.project.model.vo.InterfaceAndCollectVO;
import com.maktoub.project.service.InterfaceCollectInfoService;
import com.maktoub.project.service.InterfaceInfoService;
import com.maktoub.project.service.UserInterfaceInfoService;
import com.maktoub.project.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 帖子接口
 *
 * @author yupi
 */
@RestController
@RequestMapping("/interfaceInfo")
@Slf4j
public class InterfaceInfoController {

    @Resource
    private InterfaceInfoService interfaceInfoService;

    @Autowired
    ApiInterfaceClient apiInterfaceClient;
    //    ApiInterfaceClient tempapiInterfaceClient1;
    @Resource
    private UserService userService;

    @Resource
    private UserInterfaceInfoService userInterfaceInfoService;
    @Resource
    private InterfaceCollectInfoService interfaceCollectInfoService;



    // region 增删改查

    /**
     * 创建
     *
     * @param interfaceInfoAddRequest
     * @param request
     * @return
     */
    @PostMapping("/add")
    @AuthCheck(mustRole = "admin")
    public BaseResponse<Long> addInterfaceInfo(@RequestBody InterfaceInfoAddRequest interfaceInfoAddRequest,
                                               HttpServletRequest request) {
        if (interfaceInfoAddRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        InterfaceInfo interfaceInfo = new InterfaceInfo();
        BeanUtils.copyProperties(interfaceInfoAddRequest, interfaceInfo);
        // 校验,添加，与其他校验传入得参数就是一个add不一样
        interfaceInfoService.validInterfaceInfo(interfaceInfo, true);
        User loginUser = userService.getLoginUser(request);

        interfaceInfo.setUserId(loginUser.getId());
        boolean result = interfaceInfoService.save(interfaceInfo);
        if (!result) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR);
        }
        long newInterfaceInfoId = interfaceInfo.getId();
        return ResultUtils.success(newInterfaceInfoId);
    }

    /**
     * 删除
     *
     * @param idRequest
     * @param request
     * @return
     */
    @PostMapping("/delete")
    @AuthCheck(mustRole = "admin")
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse<Boolean> deleteInterfaceInfo(@RequestBody List<IdRequest> idRequest, HttpServletRequest request) {

        if (idRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User user = userService.getLoginUser(request);
        int i = 0;
        for (IdRequest item : idRequest) {
            long id = item.getId();
            // 判断是否存在
            InterfaceInfo oldInterfaceInfo = interfaceInfoService.getById(id);
            if (oldInterfaceInfo == null) {
                throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
            }
            // 仅本人或管理员可删除
            if (!oldInterfaceInfo.getUserId().equals(user.getId()) && !userService.isAdmin(request)) {
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
            }
            boolean b = interfaceInfoService.removeById(id);
        }

        return ResultUtils.success(true);
    }


    @PostMapping("/invoke")
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse<Object> invokeInterfaceInfo(@RequestBody InterfaceInfoInvokeRequest interfaceInfoInvokeRequest, HttpServletRequest request) {
        System.out.println("interfaceInfoInvokeRequest = " + interfaceInfoInvokeRequest);

        //合理参数
        if (interfaceInfoInvokeRequest == null || interfaceInfoInvokeRequest.getId() < 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        //接口存在
        long id = interfaceInfoInvokeRequest.getId();
        // 判断是否存在
        InterfaceInfo interfaceInfo = interfaceInfoService.getById(id);
        if (interfaceInfo == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }

        // 接口状态
        Integer status = interfaceInfo.getStatus();
        if (status == 0) {
            throw new BusinessException(ErrorCode.INTERFACE_CLOSE);
        }

        User loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }

        String accessKey = loginUser.getAccessKey();
        String secrectKey = loginUser.getSecrectKey();
        apiInterfaceClient.setAccessKey(accessKey);
        apiInterfaceClient.setSecrectKey(secrectKey);
        Map<String, Object> postRequestParam = interfaceInfoInvokeRequest.
                getPostRequestParam();

        BaseResponse<Object> objectBaseResponse = userInterfaceInfoService
                .requestGatewayWithSDK(loginUser, apiInterfaceClient, interfaceInfo, postRequestParam);
        return objectBaseResponse;
    }

    @GetMapping("/invoke")
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse<Object> invokeInterfaceInfoGet(@RequestParam Map<String, Object> requestParams,
                                                       HttpServletRequest request) {
        if(requestParams==null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Object object = requestParams.get("id");
        int id = Integer.parseInt(String.valueOf(object));


        if (id<= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        // 接口存在
        // 判断是否存在。同时获取url和method
        InterfaceInfo interfaceInfo = interfaceInfoService.getById(id);
        if (interfaceInfo == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }

        //状态
        Integer status = interfaceInfo.getStatus();
        if (status == 0) {
            throw new BusinessException(ErrorCode.INTERFACE_CLOSE);
        }

        User loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        //解决了大部分部分的重载问题，如果一个类包含的交集成员变量名，解决不了，但是一般都只用到传入的参数，相当于解决了
        BaseResponse<Object> objectBaseResponse = userInterfaceInfoService
                .requestGatewayWithSDK(loginUser, apiInterfaceClient, interfaceInfo, requestParams);
        return objectBaseResponse;


    }

    /**
     * 上线接口
     */
    @PostMapping("/online")
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse<Boolean> onlineInterfaceInfo(@RequestBody IdRequest idRequest, HttpServletRequest request) {



        if (idRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        //接口存在
        long id = idRequest.getId();
        // 判断是否存在
        InterfaceInfo interfaceInfo = interfaceInfoService.getById(id);
        if (interfaceInfo == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        String userRole = loginUser.getUserRole();
        Long id1 = loginUser.getId();
        Long userId = interfaceInfo.getUserId();
        if(!(userRole.equals("admin")||id1==userId)){
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        try {
            //接口可用，调用一遍接口
            String s;
            try {

                //todo 后期根据接口进行测试
                HttpResponse response = apiInterfaceClient.saytest("test");
                if (response.getStatus()!= 200){
                    throw new BusinessException(response.getStatus(),response.body());
                }
                s=response.body();
            } catch (Exception e) {
                throw new BusinessException(ErrorCode.INTERFACE_ERROR);
            }
            BaseResponse baseResponse = new ObjectMapper().readValue(s, BaseResponse.class);
            if (baseResponse.getCode() != 200) {
                throw new BusinessException(ErrorCode.INTERFACE_ERROR);
            }
            //修改时间
            interfaceInfo.setUpdateTime(DateTime.now());
            //修改状态
            interfaceInfo.setStatus(InterfaceStatusEnum.ONLINE.getValue());
            boolean b = interfaceInfoService.updateById(interfaceInfo);
            return ResultUtils.success(true);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            throw new BusinessException(ErrorCode.SYSTEM_ERROR);
        }

    }

    /**
     * 下线接口
     */
    @PostMapping("/offline")
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse<Boolean> offlineInterfaceInfo(@RequestBody IdRequest idRequest, HttpServletRequest request) {
        if (idRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        //接口存在
        long id = idRequest.getId();
        // 判断是否存在
        InterfaceInfo interfaceInfo = interfaceInfoService.getById(id);
        if (interfaceInfo == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }

        //下线接口没有限制，必定可以下线
//        String s = apiInterfaceClient.sayHelloGet("now");
//        if(StringUtils.isAnyBlank(s)){
//            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"请注意：接口当前不可用");
//        }

        User loginUser = userService.getLoginUser(request);
        String userRole = loginUser.getUserRole();
        Long id1 = loginUser.getId();
        Long userId = interfaceInfo.getUserId();
        if(!(userRole.equals("admin")||id1==userId)){
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }

        //修改时间
        interfaceInfo.setUpdateTime(DateTime.now());
        //修改状态
        interfaceInfo.setStatus(InterfaceStatusEnum.OFFLINE.getValue());
        boolean b = interfaceInfoService.updateById(interfaceInfo);
        return ResultUtils.success(true);
    }

    /**
     * 更新
     *
     * @param interfaceInfoUpdateRequest
     * @param request
     * @return
     */
    @PostMapping("/update")
    public BaseResponse<Boolean> updateInterfaceInfo(@RequestBody InterfaceInfoUpdateRequest interfaceInfoUpdateRequest,
                                                     HttpServletRequest request) {
        if (interfaceInfoUpdateRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        InterfaceInfo interfaceInfo = new InterfaceInfo();
        BeanUtils.copyProperties(interfaceInfoUpdateRequest, interfaceInfo);

        //为了复用接口方法，所以用InterfaceInfo,也为了用户传不改传的参数
        // 参数校验
        interfaceInfoService.validInterfaceInfo(interfaceInfo, false);
        User user = userService.getLoginUser(request);
        long id = interfaceInfoUpdateRequest.getId();
        // 判断是否存在
        InterfaceInfo oldInterfaceInfo = interfaceInfoService.getById(id);
        if (oldInterfaceInfo == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        // 对应的接口的userId没传进来

        // 仅本人或管理员可修改
        if (!(oldInterfaceInfo.getUserId().equals(user.getId())) && !(userService.isAdmin(request))) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        interfaceInfo.setUpdateTime(DateTime.now());
        boolean result = interfaceInfoService.updateById(interfaceInfo);
        return ResultUtils.success(result);
    }

    /**
     * 根据 id 获取
     *
     * @param id
     * @return
     */
    @GetMapping("/get")
    public BaseResponse<InterfaceAndCollectVO> getInterfaceInfoById(long id, HttpServletRequest request) {
        if (id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        if(loginUser==null){
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        InterfaceInfo interfaceInfo = interfaceInfoService.getById(id);
        LambdaQueryWrapper<InterfaceCollectInfo> eq = new LambdaQueryWrapper<InterfaceCollectInfo>()
                .eq(InterfaceCollectInfo::getUserId, loginUser.getId())
                .eq(InterfaceCollectInfo::getInterfaceId, id);

        InterfaceAndCollectVO interfaceAndCollectVO = new InterfaceAndCollectVO();
        BeanUtils.copyProperties(interfaceInfo,interfaceAndCollectVO);
        InterfaceCollectInfo one = interfaceCollectInfoService.getOne(eq);
        if(one!=null) {
            interfaceAndCollectVO.setCollected(true);
        }
        else {
            interfaceAndCollectVO.setCollected(false);
        }
        return ResultUtils.success(interfaceAndCollectVO);
    }

    /**
     * 获取列表（仅管理员可使用）
     *
     * @param interfaceInfoQueryRequest
     * @return
     */
    @AuthCheck(mustRole = "admin")
    @GetMapping("/list")
    public BaseResponse<List<InterfaceInfo>> listInterfaceInfo(InterfaceInfoQueryRequest interfaceInfoQueryRequest) {
        InterfaceInfo interfaceInfoQuery = new InterfaceInfo();
        if (interfaceInfoQueryRequest != null) {
            BeanUtils.copyProperties(interfaceInfoQueryRequest, interfaceInfoQuery);
        }
        QueryWrapper<InterfaceInfo> queryWrapper = new QueryWrapper<>(interfaceInfoQuery);
        List<InterfaceInfo> interfaceInfoList = interfaceInfoService.list(queryWrapper);
        return ResultUtils.success(interfaceInfoList);
    }

    /**
     * 分页获取列表
     *
     * @param interfaceInfoQueryRequest
     * @return
     */
    @GetMapping("/list/page")
    public BaseResponse<Page<InterfaceInfo>> listInterfaceInfoByPage(
            InterfaceInfoQueryRequest interfaceInfoQueryRequest) {
        if (interfaceInfoQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        long current = interfaceInfoQueryRequest.getCurrent();
        long size = interfaceInfoQueryRequest.getPageSize();

        // 限制爬虫
        if (size > 50) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        //描述信息检索
        String description = interfaceInfoQueryRequest.getDescription();
        Long id = interfaceInfoQueryRequest.getId();
        String name = interfaceInfoQueryRequest.getName();
        String url = interfaceInfoQueryRequest.getUrl();
        String requestParams = interfaceInfoQueryRequest.getRequestParams();
        String requestHeader = interfaceInfoQueryRequest.getRequestHeader();
        String responseHeader = interfaceInfoQueryRequest.getResponseHeader();
        Integer status = interfaceInfoQueryRequest.getStatus();
        String method = interfaceInfoQueryRequest.getMethod();
        Long userId = interfaceInfoQueryRequest.getUserId();
        try {
            if (userId == null) {

                String createTime = interfaceInfoQueryRequest.getCreateTime();
                createTime = createTime != null ? createTime.split(" ")[0] : null;

                String updateTime = interfaceInfoQueryRequest.getUpdateTime();
                updateTime = updateTime != null ? updateTime.split(" ")[0] : null;

                //and的关系
                LambdaQueryWrapper<InterfaceInfo> queryWrapper = new LambdaQueryWrapper<InterfaceInfo>()
                        .like(StringUtils.isNotBlank(description), InterfaceInfo::getDescription, description)
                        .like(id != null, InterfaceInfo::getId, id)
                        .like(StringUtils.isNotBlank(name), InterfaceInfo::getName, name)

                        .like(StringUtils.isNotBlank(url), InterfaceInfo::getUrl, url)

                        .like(StringUtils.isNotBlank(requestParams), InterfaceInfo::getRequestParams, requestParams)

                        .like(StringUtils.isNotBlank(requestHeader), InterfaceInfo::getRequestHeader, requestHeader)

                        .like(StringUtils.isNotBlank(responseHeader), InterfaceInfo::getResponseHeader, responseHeader)

                        .like(status != null, InterfaceInfo::getStatus, status)

                        .like(StringUtils.isNotBlank(method), InterfaceInfo::getMethod, method)
                        //时间
                        .apply(createTime != null, "DATE(create_time) = {0}", createTime)
                        .apply(updateTime != null, "DATE(update_time) = {0}", updateTime);

                Page<InterfaceInfo> interfaceInfoPage = interfaceInfoService.page(new Page<>(current, size), queryWrapper);
                return ResultUtils.success(interfaceInfoPage);
            } else {//说明是收藏，

                LambdaQueryWrapper<InterfaceCollectInfo> eq = new LambdaQueryWrapper<InterfaceCollectInfo>()

                        .eq(InterfaceCollectInfo::getUserId, userId);
                List<InterfaceCollectInfo> list = interfaceCollectInfoService.list(eq);
                Map<Long, List<InterfaceCollectInfo>> collect = list.stream().collect(Collectors.groupingBy(InterfaceCollectInfo::getInterfaceId));
                Set<Long> interfaceIds = collect.keySet();


                LambdaQueryWrapper<InterfaceInfo> interfaceWrapper = new LambdaQueryWrapper<InterfaceInfo>()
                        .like(StringUtils.isNotBlank(name), InterfaceInfo::getName, name)
                        .in(InterfaceInfo::getId,interfaceIds);

                Page<InterfaceInfo> page = interfaceInfoService.page(new Page<>(current, size), interfaceWrapper);
                return ResultUtils.success(page);
            }
        }catch (Exception e){
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR);
        }
    }


    // 这样request得到的userId肯定会被传入,上面的不能保证,防止被重放得到所有的接口
    @GetMapping("/interface_info/user_id")
    public BaseResponse<Page<InterfaceInfo> >  listInterfaceInfoByUserId (
            InterfaceInfoQueryRequest interfaceInfoQueryRequest,
            HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if(loginUser==null){
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        long userId = loginUser.getId();
        String name = interfaceInfoQueryRequest.getName();
        String description = interfaceInfoQueryRequest.getDescription();
        String url = interfaceInfoQueryRequest.getUrl();
        LambdaQueryWrapper<InterfaceInfo> queryWrapper = new LambdaQueryWrapper<InterfaceInfo>()
                .eq(InterfaceInfo::getUserId, userId)
                .like(StringUtils.isNotBlank(name),InterfaceInfo::getName,name)
                .like(StringUtils.isNotBlank(description), InterfaceInfo::getDescription, description)
                .like(StringUtils.isNotBlank(url), InterfaceInfo::getUrl, url);

        long current = interfaceInfoQueryRequest.getCurrent();
        long pageSize = interfaceInfoQueryRequest.getPageSize();
        Page<InterfaceInfo> page = interfaceInfoService.page(new Page<>(current, pageSize), queryWrapper);
        return ResultUtils.success(page);
    }

}
